#include"main.h"
/*in this function we will check if the used fd are less than max, if yes then we will find a free fd/block and
make the corresponding freelist byte to be 1, and increment the used fds
and insert out of order
#define ERR_VFS_MAKEDIR_00 "VFS_INSUFFICIENT_ARGUMENTS"
//changed to FILESYSTEM_FULL from UNABLE_TO_CREATE_NEWDIR
#define ERR_VFS_MAKEDIR_01 "FILESYSTEM_FULL"
#define ERR_VFS_MAKEDIR_02 "INVALID_CHARACTER_IN_DIRNAME"
#define ERR_VFS_MAKEDIR_03 "DIRECTORY_ALREADY_EXISTS"
//New
#define ERR_VFS_MAKEDIR_05 "VFS_NOT_MOUNTED"*/
int insertdir(char parent_Path[locationpath_size],char dir_Name[filename_size])//makedir
{
    if(strcmp(mountstate,"")==0)
    {
        printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_05);//vfs not mounted
        return 0;
    }
    if(strlen(parent_Path)==0 || strlen(dir_Name)==0)
    {
        printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_00);//insufficient arguments
        return 0;
    }
    int count=0;
    char temp[locationpath_size];
    strcpy(temp,parent_Path);
    if(strcmp(parent_Path,"/")!=0 && parent_Path[strlen(parent_Path)-1]!='/')
    {
        strcat(temp,"/");
    }
    strcat(temp,dir_Name);
    if(search_nary(temp)==1)
    {
        printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_03);// directory already exists

        return 0;
    }
    int temp1=0;
    /* if(temp[0]!='/')
     {
         printf("\nmakedir_FAILURE %s",ERR_VFS_MAKEDIR_01);

         return 0;
     }
     if(temp[strlen(temp)-1]=='/')
     {
         printf("\nmakedir_FAILURE %s",ERR_VFS_MAKEDIR_03);

         return 0;
     }*/
if(parent_Path[0]!='/')
{
    printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_02);

            return 0;
}
    while(temp1<(strlen(temp)-2))
    {
        if(temp[temp1]=='/' && temp[temp1+1]=='/')
        {
            printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_02);//invalid dir name

            return 0;
        }
        temp1++;
    }
    temp1=0;


    while(temp1<strlen(dir_Name))
    {
        if(dir_Name[temp1]=='/')
        {
            printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_02);//invalid dir name

            return 0;
        }
        temp1++;
    }
    char dir[locationpath_size];
    int y=0,j=0;
    temp1=0;
    dir[temp1]=temp[temp1];//for '/'


    temp1++;

    while(temp1<strlen(temp))
    {


        while(temp[temp1]!='/' && temp1<strlen(temp))
        {

            dir[temp1]=temp[temp1];
            temp1++;
        }
        dir[temp1]='\0';


        y=search_nary(dir);
        if(y==0)
        {
            int county=0;
            /*if(count==0)
            {
                int lengthy=temp1+1;
                while(lengthy<strlen(temp))
                {
                    if(temp[lengthy]=='/')
                    {
                        county++;
                    }
                    lengthy++;
                }
                count=1;
                int left=header.MAX_FILE_DESCRIPTORS-header.used_file_descriptors;
                if(left<(county+2))
                {
                    printf("\nmakedir_FAILURE %s",ERR_VFS_MAKEDIR_01);//file system full
                    return 0;
                }
            }*/
            if(temp1==strlen(temp))//only this node/fd needs to be created
            {

                int fill=freedescriptor();
                if(fill==-1)
                {
                    printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_01);//file system full
                    return 0;
                }
                struct FileDescriptor *fd1;
                fd1=&file_descriptors[fill];
                header.used_file_descriptors++;
                freelist[fill]=1;
                strcpy(fd1->filename,dir_Name);
                strcpy(fd1->filetype,"dir");
                fd1->filesize=0;
                strcpy(fd1->locationfullpath,temp);
                j=insert_nary(fd1);
                insert_Into_HashTable(fd1);
                insert_node(fd1 );
            }
            else
            {
                int fill=freedescriptor();
                if(fill==-1)
                {
                    printf("makedir_FAILURE %s\n",ERR_VFS_MAKEDIR_01);//file system full
                    return 0;
                }
                struct FileDescriptor *fd2;
                fd2=&file_descriptors[fill];
                header.used_file_descriptors++;
                freelist[fill]=1;
                strcpy(fd2->locationfullpath,dir);
                strcpy(fd2->filetype,"dir");
                fd2->filesize=0;
                int length=strlen(fd2->locationfullpath),slashposition,remaining;
                int extra=length,need;
                while(extra>=0)
                {
                    if(fd2->locationfullpath[extra]=='/')
                    {
                        slashposition=extra;
                        extra=0;
                    }
                    extra--;
                }
                remaining=length-slashposition;
                char extra1[filename_size];
                for(need=0; need<remaining; need++)
                {
                    extra1[need]=fd2->locationfullpath[need+slashposition+1];
                }
                strcpy(fd2->filename,extra1);
                j=insert_nary(fd2);
                insert_Into_HashTable(fd2);
                insert_node(fd2 );
            }
        }
        if(temp[temp1]=='/')
        {
            dir[temp1]=temp[temp1];
            temp1++;
        }
    }
    if(j==1 || y==1)
    {
        printf("makedir_SUCCESS\n");
        return 1;
    }
    else if(j!=1 && y!=1) return 0;
}


//s1-- source s2 parent
/*#define ERR_VFS_MOVEDIR_00 "VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_MOVEDIR_01 "CANNOT_FIND_SPECIFIED_SOURCEDIR"
//(if specified dir is not there, it is not created in this case unlike in add dir)
#define ERR_VFS_MOVEDIR_02 "CANNOT_FIND_SPECIFIED_DESTINATIONDIR"
//New
#define ERR_VFS_MOVEDIR_04 "SOURCE_CANNOT_BE_FILE"
#define ERR_VFS_MOVEDIR_05 "DESTINATION_ALREADY_HAVE_SOURCE_DIR"
//New
#define ERR_VFS_MOVEDIR_06 "CANNOT_MOVE_PARENT_TO_CHILD_DIR"
//New
#define ERR_VFS_MOVEDIR_07 "DESTINATION_CANNOT_BE_FILE"
//New
#define ERR_VFS_MOVEDIR_08 "VFS_NOT_MOUNTED"*/

int movedir_25(char s1[locationpath_size],char s2[locationpath_size])
{
    if(strcmp(mountstate,"")==0)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_08);//vfs not mounted
        return 0;
    }
    if(strlen(s1)==0 || strlen(s2)==0)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_00);//insufficient arguments
        return 0;
    }
    if(s1[strlen(s1)-1]=='/' && strlen(s1)!=1) s1[strlen(s1)-1]='\0';
    if(s2[strlen(s2)-1]=='/' && strlen(s2)!=1) s2[strlen(s2)-1]='\0';
    if(search_nary(s1)==0)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_01);//cannot find specified source dir
        return 0;
    }
    if(strcmp(searched_Descriptor->filetype,"file")==0)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_04);//source cannot be file
        return 0;
    }
    if(search_nary(s2)==0)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_02);//cannot find specified destination dir
        return 0;
    }
    if(strcmp(searched_Descriptor->filetype,"file")==0)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_07);//destination cannot be file
        return 0;
    }


    if(strncmp(s1,s2,strlen(s1))==0 && s2[strlen(s1)]=='/')//doubt vijay(will it workkk???)
    {
        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_06);//cannot move parent to child
        return 0;
    }

    struct narytree *temp,*newadd;
    temp=nroot;
    if(temp==NULL) return 0;
    else
    {

        /*if(strcmp(s1,temp->mydes->locationfullpath)==0)
        {
            printf("\nmovedir_FAILURE %s",ERR_VFS_MOVEDIR_06);
            return 0;
        }
        else*/
        {


            while(1)
            {


                if(strncmp(s1,temp->mydes->locationfullpath,strlen(temp->mydes->locationfullpath))==0 && (temp==nroot || s1[strlen(temp->mydes->locationfullpath)]=='/'))
                {
                    if(temp->child==NULL)
                    {

                        printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_01);//cannot find source dir
                        return 0;
                    }

                    else
                    {

                        temp=temp->child;
                    }
                }
                else if(temp->rightsibling==NULL && strcmp(s1,temp->mydes->locationfullpath)!=0)
                {

                    printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_01);//cannot find source dir
                    return 0;
                }
                else if(temp->rightsibling!=NULL && strcmp(s1,temp->mydes->locationfullpath)!=0)
                {

                    temp=temp->rightsibling;
                }



                if(strcmp(s1,temp->mydes->locationfullpath)==0)
                {


                    if((temp->parent!=NULL) && (temp->rightsibling==NULL) && (temp->leftsibling!=NULL))
                    {
                        char errorhandling[locationpath_size];
                        strcpy(errorhandling,s2);
                        if(strcmp(errorhandling,"/")!=0)
                        {
                            strcat(errorhandling,"/");
                        }
                        strcat(errorhandling,temp->mydes->filename);
                        int find=search_nary(errorhandling);
                        if(find==1)
                        {
                            printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_05);//destination already have source dir
                            return 0;
                        }
                        struct narytree *tempo;
                        tempo=(struct narytree *)malloc(sizeof(struct narytree));
                        //tempo=temp;
                        //header.used_file_descriptors--;
                        //freelist[temp->mydes->locationblocknumber]=0;

                        //free_nary(tempo->child);
                        temp->leftsibling->rightsibling=NULL;
                        tempo->mydes=temp->mydes;
                        tempo->parent=NULL;
                        tempo->rightsibling=NULL;
                        tempo->leftsibling=NULL;

                        if(temp->child!=NULL)
                        {
                            tempo->child=temp->child;
                            //temp->child->parent=NULL;
                            tempo->child->parent=tempo;
                            struct narytree *tempextra;
                            tempextra=tempo->child;

                            while(tempextra->rightsibling!=NULL)
                            {
                                tempextra->rightsibling->parent=tempo;
                                tempextra=tempextra->rightsibling;
                            }
                        }
                        else tempo->child=NULL;
                        delete_node(bst_root,temp->mydes->locationfullpath);////////////////

                        free(temp);/////////////////////////


                        if(strcmp(s2,"/")!=0)
                        {
                            strcat(s2,"/");
                        }

                        strcat(s2,tempo->mydes->filename);
                        strcpy(tempo->mydes->locationfullpath,s2);
                        int state=move_nary(tempo);///////////////////////////////////////////////
                        if(state==1) printf("movedir_SUCCESS\n");
                        return 1;
                    }
                    else if((temp->parent!=NULL) && (temp->rightsibling!=NULL) && (temp->leftsibling!=NULL))
                    {
                        char errorhandling[locationpath_size];
                        strcpy(errorhandling,s2);
                        if(strcmp(errorhandling,"/")!=0)
                        {
                            strcat(errorhandling,"/");
                        }
                        strcat(errorhandling,temp->mydes->filename);
                        int find=search_nary(errorhandling);
                        if(find==1)
                        {
                            printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_05);
                            return 0;
                        }
                        struct narytree *tempo;
                        tempo=(struct narytree *)malloc(sizeof(struct narytree));

                        temp->leftsibling->rightsibling=temp->rightsibling;
                        temp->rightsibling->leftsibling=temp->leftsibling;
                        tempo->mydes=temp->mydes;
                        tempo->parent=NULL;
                        tempo->rightsibling=NULL;
                        tempo->leftsibling=NULL;
                        if(temp->child!=NULL)
                        {
                            //temp->child->parent=NULL;
                            tempo->child=temp->child;
                            tempo->child->parent=tempo;
                            struct narytree *tempextra;
                            tempextra=tempo->child;

                            while(tempextra->rightsibling!=NULL)
                            {
                                tempextra->rightsibling->parent=tempo;
                                tempextra=tempextra->rightsibling;
                            }
                        }
                        else tempo->child=NULL;


                        delete_node(bst_root,temp->mydes->locationfullpath);
                        free(temp);
                        if(strcmp(s2,"/")!=0)
                        {
                            strcat(s2,"/");
                        }
                        strcat(s2,tempo->mydes->filename);
                        strcpy(tempo->mydes->locationfullpath,s2);
                        int state=move_nary(tempo);
                        if(state==1) printf("movedir_SUCCESS\n");
                        return 1;
                    }
                    else if((temp->parent!=NULL) && (temp->rightsibling!=NULL) && (temp->leftsibling==NULL))
                    {
                        char errorhandling[locationpath_size];
                        strcpy(errorhandling,s2);
                        if(strcmp(errorhandling,"/")!=0)
                        {
                            strcat(errorhandling,"/");
                        }
                        strcat(errorhandling,temp->mydes->filename);
                        int find=search_nary(errorhandling);
                        if(find==1)
                        {
                            printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_05);
                            return 0;
                        }
                        struct narytree *tempo;
                        tempo=(struct narytree *)malloc(sizeof(struct narytree));
                        temp->rightsibling->leftsibling=NULL;
                        temp->parent->child=temp->rightsibling;
                        tempo->mydes=temp->mydes;
                        tempo->parent=NULL;
                        tempo->rightsibling=NULL;
                        tempo->leftsibling=NULL;
                        if(temp->child!=NULL)
                        {
                            //temp->child->parent=NULL;
                            tempo->child=temp->child;
                            tempo->child->parent=tempo;
                            struct narytree *tempextra;
                            tempextra=tempo->child;

                            while(tempextra->rightsibling!=NULL)
                            {
                                tempextra->rightsibling->parent=tempo;
                                tempextra=tempextra->rightsibling;
                            }
                        }
                        else tempo->child=NULL;

                        delete_node(bst_root,temp->mydes->locationfullpath);
                        free(temp);
                        if(strcmp(s2,"/")!=0)
                        {
                            strcat(s2,"/");
                        }
                        strcat(s2,tempo->mydes->filename);
                        strcpy(tempo->mydes->locationfullpath,s2);
                        int state=move_nary(tempo);
                        if(state==1) printf("movedir_SUCCESS\n");
                        return 1;
                    }
                    else if((temp->parent!=NULL) && (temp->rightsibling==NULL) && (temp->leftsibling==NULL))
                    {


                        char errorhandling[locationpath_size];
                        strcpy(errorhandling,s2);
                        if(strcmp(errorhandling,"/")!=0)
                        {
                            strcat(errorhandling,"/");
                        }
                        strcat(errorhandling,temp->mydes->filename);
                        int find=search_nary(errorhandling);
                        if(find==1)
                        {
                            printf("movedir_FAILURE %s\n",ERR_VFS_MOVEDIR_05);
                            return 0;
                        }
                        struct narytree *tempo;
                        tempo=(struct narytree *)malloc(sizeof(struct narytree));
                        temp->parent->child=NULL;
                        tempo->mydes=temp->mydes;
                        tempo->parent=NULL;
                        tempo->rightsibling=NULL;
                        tempo->leftsibling=NULL;
                        if(temp->child!=NULL)
                        {
                            //temp->child->parent=NULL;
                            tempo->child=temp->child;
                            tempo->child->parent=tempo;

                            struct narytree *tempextra;
                            tempextra=tempo->child;

                            while(tempextra->rightsibling!=NULL)
                            {
                                tempextra->rightsibling->parent=tempo;
                                tempextra=tempextra->rightsibling;
                            }

                        }

                        else tempo->child=NULL;

                        delete_node(bst_root,temp->mydes->locationfullpath);
                        free(temp);
                        if(strcmp(s2,"/")!=0)
                        {
                            strcat(s2,"/");
                        }
                        strcat(s2,tempo->mydes->filename);
                        strcpy(tempo->mydes->locationfullpath,s2);

                        int state=move_nary(tempo);
                        if(state==1) printf("movedir_SUCCESS\n");
                        return 1;
                    }


                }






            }
        }
    }
}




/*#define ERR_VFS_LISTDIR_00 "VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_LISTDIR_01 "CANNOT_FIND_SPECIFIED_PATH_OR_DIR"
#define ERR_VFS_LISTDIR_02 "INVALID_FLAG"
#define ERR_VFS_LISTDIR_03 "VFS_NOT_MOUNTED"
#define ERR_VFS_LISTDIR_04 "CANNOT_CREATE_OUTPUTFILE"*/
int listdir_25(char s1[locationpath_size], int flag, char s2[500])
{

    if(strcmp(mountstate,"")==0)
    {
        printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_03);//vfs not mounted
        return 0;
    }

    if(strlen(s1)==0 || strlen(s2)==0)
    {
        printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_00);//insufficient arguments
        return 0;
    }

    if(s1[strlen(s1)-1]=='/' && strlen(s1)!=1) s1[strlen(s1)-1]='\0';
    if(s2[strlen(s2)-1]=='/' && strlen(s2)!=1) s2[strlen(s2)-1]='\0';

    if(search_nary(s1)==0)
    {
        printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_01);//path not found
        return 0;
    }
    struct narytree *temp,*newadd;
    temp=nroot;
    FILE *fpl;
    /*fpl=fopen(s2,"r");
    if(fpl==NULL)
    {
        printf("\nlistdir_FAILURE %s",ERR_VFS_LISTDIR_03);
        return 0;
    }
    fclose(fpl);
    if(temp==NULL)
    {
        printf("\nlistdir_FAILURE %s",ERR_VFS_LISTDIR_04);
        return 0;
    }
    else*/
    {


        while(1)
        {

            fpl=fopen(s2,"w");
            if(fpl==NULL)
            {
                printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_04);//cannot create outputfile
                return 0;
            }
            if(strcmp(s1,temp->mydes->locationfullpath)==0)
            {
                // fpl=fopen(s2,"w");
                /* if(temp->child!=NULL)
                 {
                     temp=temp->child;
                 }*/
                //else fclose(fpl);
                //else return 0;



                /*if(fpl==NULL)
                {
                    printf("\nlistdir_FAILURE %s",ERR_VFS_LISTDIR_03);
                    return 0;
                }
                */

                if(flag==0)
                {
                    int state=nonrecur_nary(temp->child,fpl);
                    fclose(fpl);
                    /*if(state==1)*/
                    printf("listdir_SUCCESS\n");
                    return 1;
                }
                else if(flag==1)
                {
                    int state=recur_nary(temp->child,fpl);
                    fclose(fpl);
                    /*if (state==1)*/
                    printf("listdir_SUCCESS\n");
                    return 1;
                }
                else
                {
                    printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_02);
                    fclose(fpl);
                    return 0;
                }
            }

            else if(strncmp(s1,temp->mydes->locationfullpath,strlen(temp->mydes->locationfullpath))==0 && (temp==nroot || s1[strlen(temp->mydes->locationfullpath)]=='/'))
            {
                if(temp->child==NULL)
                {
                    printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_01);
                    fclose(fpl);
                    return 0;
                }

                else
                {
                    temp=temp->child;
                }
            }
            else if(temp->rightsibling==NULL)
            {
                printf("listdir_FAILURE %s\n",ERR_VFS_LISTDIR_01);
                fclose(fpl);
                return 0;
            }
            else if(temp->rightsibling!=NULL)
            {
                temp=temp->rightsibling;
            }



        }
        return 1;
    }

}



/*#define ERR_VFS_DELETEDIR_00 "VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_DELETEDIR_01 "CANNOT_FIND_SPECIFIED_DIR"
#define ERR_VFS_DELETEDIR_02 "DIRECTORY_IS_NOT_EMPTY"
//New
#define ERR_VFS_DELETEDIR_04 "VFS_NOT_MOUNTED"*/
int deletedir_25(char s1[locationpath_size])
{
    if(strcmp(mountstate,"")==0)
    {
        printf("deletedir_FAILURE %s\n",ERR_VFS_DELETEDIR_04);//vfs not mounted
        return 0;
    }
    if(strlen(s1)==0)
    {
        printf("deletedir_FAILURE %s\n",ERR_VFS_DELETEDIR_00);//insufficinet arguments

        return 0;
    }

    /*int q=0;
    while(q<(strlen(s1)-1))
    {


        if(s1[q]=='/' && s1[q+1]=='/')
        {
            printf("\ndeletedir_FAILURE %s",ERR_VFS_DELETEDIR_03);

            return 0;

        }
        q++;
    }
    if(s1[strlen(s1)-1]=='/')
    {
        printf("\ndeletedir_FAILURE %s",ERR_VFS_DELETEDIR_03);

        return 0;
    }
    if(s1[0]!='/')
    {
        printf("\ndeletedir_FAILURE %s",ERR_VFS_DELETEDIR_03);

        return 0;
    }
    q=0;
    while(q<strlen(s1))
    {


        if(!((s1[q]>='a' && s1[q]<='z') || (s1[q]>='A' &&
                                            s1[q]<='Z') || (s1[q]>='0' && s1[q]<='9')
                || s1[q]=='-' || s1[q]=='_' || s1[q]=='/'))
        {
            printf("\ndeletedir_FAILURE %s",ERR_VFS_DELETEDIR_03);

            return 0;
        }
        q++;
    }*/
    if(s1[strlen(s1)-1]=='/' && strlen(s1)!=1) s1[strlen(s1)-1]='\0';

    int state;

    state=delete_nary(s1);
    if(state==1)
    {
        delete_From_HashTable(s1);
        delete_node(bst_root,s1);
    }
    if(state==1) printf("deletedir_SUCCESS\n");
    return 1;


}


